home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS26.ADF / SoundScape / AztecExamples / vu.c < prev    next >
C/C++ Source or Header  |  1989-01-26  |  8KB  |  290 lines

  1. /*      VU.C            VU Meter for the Sampler
  2.  
  3.         (c) 1987        Todor Fay
  4.  
  5.     AZTEC C version
  6.  
  7. */
  8.  
  9. #include "exec/exec.h"
  10. #include "exec/types.h"
  11. #include "soundscape.h"
  12. #include "intuition/intuition.h"
  13.  
  14. /*      Images for the LEDs.  A red LED for lighting, 
  15.         a blue LED for turning it back off 
  16.         (the background color.)
  17. */
  18.  
  19. UWORD redleddata[] = {        /* 16 x 3 */ 
  20. 65535,        
  21. 65535,        
  22. 65535,        
  23. 65535,        
  24. 65535,        
  25. 65535,        
  26. };
  27.  
  28. struct Image redledimage = { 0,0,16,3,2,redleddata,3,0,0 };
  29.  
  30. UWORD blueleddata[] = {        /* 16 x 3 */ 
  31. 0,        
  32. 0,        
  33. 0,        
  34. 0,        
  35. 0,        
  36. 0,        
  37. };
  38.  
  39. struct Image blueledimage = { 0,0,16,3,2,blueleddata,3,0,0 };
  40.  
  41. /*      We don't need any Intuition Gadgets, just a 
  42.         window to display the LEDs in.
  43.         This was designed with Power Windows.
  44. */
  45.  
  46. struct NewWindow NewWindowStructure = {
  47.         0,0,
  48.         250,20,
  49.         0,1,
  50.         NULL,
  51.         WINDOWDRAG+WINDOWDEPTH,
  52.         NULL,
  53.         NULL,
  54.         "VU Meter",
  55.         NULL,
  56.         NULL,
  57.         5,5,
  58.         0,0,
  59.         WBENCHSCREEN
  60. };
  61.  
  62. short thisport;                     /* This port's id. */
  63. long SoundScapeBase;                /* SoundScape library. */
  64. long IntuitionBase;
  65.  
  66. /*      We need a place to store the Sampler's
  67.         output routine address, since we are replacing
  68.         the code pointer in its port structure
  69.         with our own.
  70. */
  71.  
  72. void (*sampleroutcode) ();
  73. struct Window *vuwindow;        /* Display window. */
  74.  
  75. /*      We need an array of velocity values for each
  76.         note that is being played.  These are zeroed
  77.         for no note. 
  78.         If you add up all the velocities in this 
  79.         array, you should get totalvolume, which
  80.         is used to determine the number of LEDs to
  81.         light.
  82. */
  83.  
  84. unsigned char velocity[128];        
  85. unsigned short totalvolume;
  86.  
  87. insertoutcode(note)
  88.  
  89. /*      This output routine is not given to the Patch
  90.         Panel in the AddMidiPort call.  Instead, this
  91.         routine replaces the Sampler output code, and
  92.         then calls it.  So, this is inserted there by
  93.         the open routine.
  94.  
  95.         Check the note status.  If it is NOTEON or NOTEOFF,
  96.         we want to use it for the display.
  97.  
  98.         Start by decrementing the totalvolume by 
  99.         velocity[note->value].  If this is a NOTEOFF
  100.         event, this reduces totalvolume appropriately.
  101.         If this is a NOTEON event, this clears any
  102.         previous NOTEON that was stored.  This is
  103.         neccessary because we aren't supporting multiple
  104.         playing of the same note (for simplicity.)
  105.  
  106.         If this is a NOTEON event, increment totalvolume
  107.         by the velocity of this note.  Store this
  108.         velocity in the velocity array.  
  109.  
  110.         Else, for a NOTEOFF event, simply put zero in
  111.         the velocity array - there is no note being
  112.         played.
  113.  
  114.         Compute how many LEDs should be on from 
  115.         totalvolume.  Each additional LED represents
  116.         a doubling in volume, so figure what the most
  117.         significant bit of totalvolume is.
  118.  
  119.         If the new top LED position (newvupos) is
  120.         greater than the currently displayed one
  121.         (vupos), draw in the extra LEDs.  Else,
  122.         if newvupos is less than vupos, erase 
  123.         LEDs down to newvupos.
  124.  
  125.         Finally, forward the note event to the 
  126.         Sampler by calling its output routine.
  127. */
  128.         
  129. struct Note *note;
  130.  
  131. {
  132.     unsigned char status = note->status & 0xF0;
  133.     static short vupos = 0;
  134.     short newvupos, index;
  135.     if (sampleroutcode) {
  136.         if ((status == NOTEON) || (status == NOTEOFF)) {
  137.             totalvolume -= velocity[note->value];
  138.             if ((status == NOTEON) && note->velocity) {
  139.                 totalvolume += note->velocity;
  140.                 velocity[note->value] = note->velocity;
  141.             }
  142.             else velocity[note->value] = 0;
  143.             newvupos = 0;
  144.             index = 4;
  145.             for (;index < totalvolume; index = index << 1)
  146.                  newvupos++;
  147.             if (newvupos < vupos) {
  148.                 for (;vupos > newvupos; vupos--) 
  149.                     DrawImage(vuwindow->RPort,
  150.                         &blueledimage,-10 + vupos * 20,13);
  151.             }
  152.             else if (newvupos > vupos) {
  153.                 vupos++;
  154.                 for (;vupos <= newvupos; vupos++) 
  155.                     DrawImage(vuwindow->RPort,
  156.                         &redledimage,-10 + vupos * 20,13);
  157.             }
  158.             vupos = newvupos;
  159.         }
  160.         (*sampleroutcode) (note);
  161.     }
  162.     else FreeNode(note);
  163. }
  164.  
  165. outcode(note)
  166.  
  167. /*      This, the outcode for this module, does
  168.         nothing.  
  169. */
  170.  
  171. struct Note *note;
  172.  
  173. {
  174.     enteraztec();
  175.     FreeNode(note);
  176.     leaveaztec();
  177. }
  178.  
  179.  
  180. opencode(direction)
  181.  
  182. /*      This installs the VU meter.
  183.         
  184.         If this is to install the output routine:
  185.  
  186.         Get the Port structure for the Sampler.
  187.         If the Sampler already has its output
  188.         code stolen, (samplerport->show has somebody's
  189.         port id) do nothing.  Else, open the window,
  190.         give samplerport->outcode insertoutcode 
  191.         and put the Sampler's output code
  192.         in samplercode.  Set samplerport->show to
  193.         this port's id, so no other module will
  194.         monkey with it.
  195. */
  196.  
  197. char direction;
  198.  
  199. {
  200.     short i;
  201.     struct Port *samplerport;
  202.     enteraztec();
  203.     if (!direction) {
  204.         samplerport = (struct Port *) 
  205.             MidiPort(FindMidiPort("sampler"));
  206.         if (samplerport) {
  207.             if (samplerport->show) {
  208.                 CloseMidiPort(samplerport->show,0);
  209.             }
  210.             if (!samplerport->show) {
  211.                 vuwindow = (struct Window *) 
  212.                     OpenWindow(&NewWindowStructure);
  213.                 if (vuwindow) {
  214.                     totalvolume = 0;
  215.                     for (i=0; i < 128; i++) 
  216.                         velocity[i] = 0;        
  217.                     sampleroutcode = samplerport->outcode;
  218.                     samplerport->outcode = insertoutcode;
  219.                     samplerport->show = thisport;
  220.             leaveaztec();
  221.                     return(1);
  222.                 }
  223.             }
  224.         }
  225.     }
  226.     leaveaztec();
  227.     return(0);
  228. }
  229.  
  230.  
  231. closecode(direction)
  232.  
  233. /*      This deactivates the VU Meter.
  234.  
  235.         Simply return the Sampler's output routine 
  236.         to its Port structure and clear 
  237.         samplerport->show.  Close the display
  238.         window.
  239. */
  240.  
  241.     struct Port *samplerport;
  242.     enteraztec();
  243.     if (!direction) {
  244.         samplerport = (struct Port *) 
  245.             MidiPort(FindMidiPort("sampler"));
  246.         if (samplerport && sampleroutcode) {
  247.             samplerport->outcode = sampleroutcode;
  248.             samplerport->show = 0;
  249.         }
  250.         if (vuwindow) CloseWindow(vuwindow);
  251.         vuwindow = 0;
  252.     }
  253.     leaveaztec();
  254.     return(1);
  255. }
  256.  
  257. /*      The main program is standard with one addition:
  258.         After installing this port, call OpenMidiPort
  259.         to activate it.  This is needed because there
  260.         is no icon for the user to click on.  We
  261.         could have added that icon, but it would be
  262.         one more item on the Patch Panel, cluttering
  263.         it and causing some confusion since nothing
  264.         can be sent directly to it.
  265.         There is a chance OpenMidiPort will fail.  This
  266.         is because the Sampler's output routine was
  267.         already stolen.  If so, there is no need to
  268.         stick around, so call RemoveMidiPort and leave.
  269.         Normally, RemoveMidiPort is done by SoundScape
  270.         when it closes down, but this time we'll
  271.         do it ourselves to get out early.
  272. */
  273.  
  274. main() {
  275.     IntuitionBase = OpenLibrary("intuition.library",0);
  276.     SoundScapeBase = OpenLibrary("soundscape.library",0);
  277.     if (SoundScapeBase) {
  278.         CloseLibrary(SoundScapeBase);
  279.         thisport = AddMidiPort(opencode,closecode,0,
  280.             outcode,0,0,-1,"vu meter");
  281.         if (OpenMidiPort(thisport,0)) {
  282.             SetTaskPri(FindTask(0),-20);
  283.             while (MidiPort(thisport)) Delay(100);
  284.         }
  285.         else RemoveMidiPort(thisport);
  286.     }
  287.     CloseLibrary(IntuitionBase);
  288. }
  289.